<?php

namespace App\Http\Controllers\App;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Baqi\Alipay\AlipaySubmit;
use App\Baqi\Alipay\AlipayNotify;
use App\Baqi\Alipayapp\Alipayapp;
use App\Baqi\Wxpay\WechatAppPay;
use App\Models\PayHistory;
use App\Models\Pay as PayModel;
use App\Models\User;
use App\Models\ShopUserCenter;
use App\Models\Order;
use App\Baqi\Sdpay\Sdpay;

class PayController extends Controller
{

    public $payClass = [0 => '异常操作', 1 => 'alipayapp', 2 => 'wxpayapp' , 3 => 'balance', 4 => 'shande'];

    public $payName  = [0 => '异常操作', 1 => '支付宝', 2 => '微信' , 3 => '余额', 4 => '衫德快捷支付'];

    public function test() {

        //$data = $this->getLog();

        //$params = unserialize($data);
        //dump($params);
        //$this->notifyAli($params);
        echo $this->front_url_sd   = url('api/pay/frontsd');
    }

    public $notify_url_ali;//支付宝异步地址

    public $notify_url_wx;//微信异步地址

    public $notify_url_sd;//善德异步地址

    public $front_url_sd;//善德同步地址

    public function __construct() 
    {
        $this->notify_url_ali = url('api/pay/notifyAli');

        $this->notify_url_wx  = url('api/pay/notifyWx');

        $this->notify_url_sd  = url('api/pay/notifsd');

        $this->front_url_sd   = url('api/pay/frontSd');
    }

    /**
     * 获得支付列表
     */
    public function payList (Request $request) 
    {

        $type = $request->input('type', 0);

        $payModel = PayModel::where('status', PayModel::STATUS_BEGIN)->where('platform', $type)->get();

        $data = [];

        foreach ($payModel as $key => $value) {

            $data[$key]['name']      = $value->name;
            $data[$key]['pay_type']  = $this->payClass[$value->type];
            //$data[$key]['icon']      = $value->icon;
            $data[$key]['icon']      = $value->icon;
        }

        return self::json($data);
    }

    /**
     * 债券盘支付
     * @param  Request $request [description]
     * @return [type]           [description]
     */
    public function balanceZPay(Request $request) {

        $order_sn   = $request->input('order_sn');//订单编码
        $money      = $request->input('money');//商品金额
        $id         = session('user_id');
        $password   = $request->input('password');

        /*$user       = new User*/
        

        //业务逻辑 判断支付金额和订单金额是否一直
        $orderModel = new Order();

        $orderObj = $orderModel->where('order_sn', $order_sn)->where('status', 0)->first();

        if (empty($orderObj)) {
            return self::error('该订单支付失败');
        }

        if ( $orderObj['pay_amount'] != $money) {
            return self::error('支付金额异常');
        }

  
        $userObj    = User::where('id', $id)->first();
        // 验证支付密码
        if (!User::check_pwd($password, $userObj->pay_pwd) ) 
            return self::json([],'支付密码错误',308);
        // 验证账户金额是否够用
        if ( $userObj->balance < $money ) 
            return self::json([],'余额不足',302);
        
        $userObj->balance  -= $money;
        $userObj->save();

        //订单业务处理
        $result     = $orderModel->edit_pay_order($order_sn, PayModel::TYPE_BALANCEPAY);

        $remark = '成功';

        if ($result == false) {

            $userObj->balance  += $money;
            $userObj->save();

            $remark     = ($result == false) ? '订单业务流程更改失败' : '订单业务流程更改成功';
        }
        
        $payHistory = new PayHistory();
   
        $payHistory->ordernum  =  $order_sn;
        $payHistory->money     =  $money;
        $payHistory->type      =  3;
        $payHistory->status    =  $result ? 1 : 0;
        $payHistory->remark    =  $remark;
        $payHistory->payid     =  $id;
        $payHistory->save();

        return self::success('成功');
    }

    /**
     * 返利盘支付
     * @param  Request $request [description]
     * @return [type]           [description]
     */
    public function balanceFPay(Request $request) {


        $orderNum    = $request->input('orderNum');//订单编码
        $money       = $request->input('money');//商品金额
        $id          = $request->input('id');

        //业务逻辑
        $orderModel  = new Order();

        //订单业务处理
        $result      = $orderModel->edit_pay_order($data['out_trade_no'], PayModel::TYPE_BALANCEPAY);
        $remark      = ($result == false) ? '订单业务流程更改失败' : '订单业务流程更改成功';

        $shopUserObj = ShopUserCenter::where('user_id', $id)->first();

        $shopUserObj->balance  -= $money;

        $shopUserObj->save();

        $params['ordernum']   =  $orderNum;
        $params['money']      =  $money;
        $params['type']       =  2;
        $params['status']     =  $result ? 1 : 0;
        $params['remark']     =  $remark;
        $params['payid']      =  $id;

        $payHistory = new PayHistory();

        $payHistory->setAttributes($params);
       
        $payHistory->save();
    }

    /**
     * 支付宝App支付
     * @param  Request $request [description]
     * @return [type]           [description]
     */
    public function getAliPayAppSign (Request $request) 
    {

        //判断支付方法是否开启
        $result = $this->checkStatus('alipayapp');

        if ($result == false)  {
            return self::error('未开启支付宝支付');
        }

        $params['order_sn']  = $request->input('order_sn');//订单编码
        $params['subject']   = $request->input('goodsName',$params['order_sn']);//订单名称（商品名称）
        $params['money']     = $request->input('money');//商品金额
        $params['body']      = $request->input('remark', '暂无描述');////商品描述

        if (empty($params['order_sn'])  || empty($params['money'])) {
            return self::error('参数不全');
        }

        //查询订单核对金币数
        $orderObj = Order::where('order_sn', $params['order_sn'])->where('status', 0)->first();
 
/*        if (empty($orderObj) || $orderObj['pay_amount'] != $params['money']) {
            return self::error('支付金额异常');
        }*/
        if (empty($orderObj)) {
            return self::error('该订单已支付');
        }

        if ( $orderObj['pay_amount'] != $params['money']) {
            return self::error('支付金额异常');
        }
        //获得配置信息
        $config = $this->getConfig('alipayapp');
        //获得回调地址
        $config['notify_url'] = $this->notify_url_ali;

        $app = new AlipayApp($config);

        
        $sign   = $app->getSign($params);
 
        return self::json(['sign'=>$sign]);

    }

    /**
     * 微信生成签名
     * @param  [type] $ordernum [description]
     * @param  [type] $money    [description]
     * @return [type]           [description]
     */
    public function getWxAppSign(Request $request) 
    {

        //判断支付方法是否开启
        $result = $this->checkStatus('wxpayapp');

        if ($result == false)  {
            return self::error('未开启微信支付');
        }

        $order_sn  = $request->input('order_sn');//订单编码
        $goodsName = $request->input('goodsName',$order_sn);//订单名称（商品名称）
        $money     = $request->input('money');//商品金额
        $body      = $request->input('remark', ' ');////商品描述

        if (empty($order_sn) || empty($goodsName) || empty($money)) {
            return self::error('参数不全');
        }

        //查询订单核对金币数
        $orderObj = Order::where('order_sn', $order_sn)->where('status', 0)->first();

        if (empty($orderObj)) {
            return self::error('该订单已支付');
        }

        if ( $orderObj->pay_amount != $money) {
            return self::error('支付金额异常');
        }

        //获得配置信息
        $config = $this->getConfig('wxpayapp');
        //获得回调地址
        $config['notifyUrl'] = $this->notify_url_wx;
        //请求微信验证
        $wechat_pay = new WechatAppPay($config['appid'], $config['mchid'], $config['notifyUrl'], $config['key']);

        //微信金额单位为分
        $money  = $money * 100;
        $params = ['out_trade_no' => $order_sn, 'total_fee' => $money, 'trade_type' =>'APP','body' => $body];
        //生成加密签名
        $params = $wechat_pay->unifiedOrder($params);


        $data   = $wechat_pay->getAppPayParams($params['prepay_id']);

        return self::json($data);
    }


    /**
     * 获得善德的url
     * @param  Request $request [description]
     * @return [type]           [description]
     */
    public function getSdUrl(Request $request) 
    {
        $order_sn  = $request->input('order_sn');//订单编码

        $money     = $request->input('money');//商品金额

        //判断支付方法是否开启
        $result = $this->checkStatus('shande');

        if ($result == false)  {
            return self::error('未开启该支付');
        }


        if (empty($order_sn) ||  empty($money)) {
            return self::error('参数不全');
        }

        //查询订单核对金币数
        $orderObj = Order::where('order_sn', $order_sn)->where('status', 0)->first();

        if (empty($orderObj)) {
            return self::error('该订单已支付');
        }

        if ( $orderObj->pay_amount != $money) {
            return self::error('支付金额异常');
        }

        $url       = url('api/pay/sdpay?order_sn='.$order_sn.'&money='.$money);

        return self::json(['url' => $url]);
    }
    /**
     * 衫德支付
     * @return [type] [description]
     */
    public function sdPay(Request $request) 
    {
        //判断支付方法是否开启
        $result = $this->checkStatus('shande');

        if ($result == false)  {
            return self::error('未开启该支付');
        }

        $order_sn  = $request->input('order_sn');//订单编码
        $goodsName = $request->input('goodsName',$order_sn);//订单名称（商品名称）
        $money     = $request->input('money');//商品金额
        $body      = $request->input('remark', ' ');////商品描述

        if (empty($order_sn) || empty($goodsName) || empty($money)) {
            return self::error('参数不全');
        }

        //查询订单核对金币数
        $orderObj = Order::where('order_sn', $order_sn)->where('status', 0)->first();

        if (empty($orderObj)) {
            return self::error('该订单已支付');
        }

        if ( $orderObj->pay_amount != $money) {
            return self::error('支付金额异常');
        }

        //获得配置信息
/*        $config = $this->getConfig('sdapppay');
        //获得回调地址
        $config['notifyUrl'] = $this->notify_url_sd;
        $config['frontUrl']  = $this->front_url_sd;*/

        //获得随机数
        //$rand = mt_rand(10,99);
        $sdpay = new Sdpay();

        $sdpay->setConfig(['order_sn'=> $order_sn, 'money'=> $money, 'notifyUrl'=>$this->notify_url_sd , 'frontUrl' => $this->front_url_sd]);

        $html = $sdpay->getData();

        echo $html;
    }

    /**
     * 支付宝回调
     * @return [type] [description]
     */
    public function notifyAli(Request $request) 
    {
        $params = $request->all();
        //$this->logResult(json_encode($params));
/*        $params = json_decode('{"gmt_create":"2017-07-13 15:20:26","charset":"UTF-8","seller_email":"gexin2017@126.com","subject":"14159671f2f1935","sign":"f1LaQ0fgGr4DfUBnPOdfEsgorGRxM7el0AFdiHsnK2iiZ5WEpS2aq83glXuitl24Y67ECg99EC1mlfgbB+u4KD4eKP5zzBd5JRP+os8DWaX9aIbnvrDxPkO\/5d87+Imr8O1tHJJp\/AIAEB3rX+WH7AtFEUexEVbH71+6iw9vKzHCW1tGDMM\/YYnYNpYEK2whyQe1ob8KxRuCpnIzt0JgQDJ\/rxnUwEqB96pDNuThZTzXJ+yukxeNvt5o3IAuvBQpZ1dJ33HQFMcbV2TasXrtkOSiczJtEmkbj355WtuKF97ZZa5ByatZXfKY05cuSd36NXmm20TTF1IgrIQ30G3Hpg==","body":"\u6682\u65e0\u63cf\u8ff0","buyer_id":"2088702046715107","invoice_amount":"0.01","notify_id":"c2a57c6f19307d388aac211320962d8gru","fund_bill_list":"[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]","notify_type":"trade_status_sync","trade_status":"TRADE_SUCCESS","receipt_amount":"0.01","app_id":"2017071007700291","buyer_pay_amount":"0.01","sign_type":"RSA2","seller_id":"2088721441254114","gmt_payment":"2017-07-13 15:20:27","notify_time":"2017-07-13 15:20:27","version":"1.0","out_trade_no":"14159671f2f1935","total_amount":"0.01","trade_no":"2017071321001004100243505499","auth_app_id":"2017071007700291","buyer_logon_id":"152****8189","point_amount":"0.00"}',true);*/
        $config = $this->getConfig('alipayapp');

        $app = new AlipayApp($config);
        
        if ($app->check($params)) {

            if ($params['trade_status'] = "TRADE_SUCCESS" || $params['trade_status'] = "TRADE_FINISHED") {
                  //业务逻辑
                $orderModel = new Order();
                //核实订单是否为平台订单
                $result     = $orderModel->check($params['out_trade_no'], $params['total_amount']);

                if ($result == false) {

                    $params['remark'] = '非法订单';
                    $params['status'] = 2;
                } else {
                    //订单业务处理
                    $result = $orderModel->edit_pay_order($params['out_trade_no'], PayModel::TYPE_ALIPAY);

                    $params['remark'] = ($result == false) ? '订单业务流程更改失败' : '订单业务流程更改成功';
                    $params['status'] = ($result == false) ? 2 : 1;  
                }
            }
            echo "success";
        } else {
            $params['status'] = 2;
            echo "error";
        }
        //添加日志
        $this->getAliHistory($params);
    }

    /**
     * 微信回调
     * @return [type] [description]
     */   
    public function notifyWx(Request $request) 
    {

        $config = $this->getConfig('wxpayapp');

        $info = file_get_contents('php://input');
        
        libxml_disable_entity_loader(true);
        
        $data = json_decode(json_encode(simplexml_load_string($info, 'SimpleXMLElement', LIBXML_NOCDATA)),true);

        if ($data['return_code'] == 'SUCCESS') {

            //业务逻辑
            $orderModel = new Order();

            $data['total_fee'] = $data['total_fee']/100;
            //核实订单是否为平台订单
            $result     = $orderModel->check($data['out_trade_no'], $data['total_fee']);

            if ($result == false) {
                
                $data['status'] = 2;
                $data['remark'] = '非法订单';
            } else {
                
                //订单业务处理
                $result         = $orderModel->edit_pay_order($data['out_trade_no'], PayModel::TYPE_WXPAY);
                $data['remark'] = ($result == false) ? '订单业务流程更改失败' : '订单业务流程更改成功';
                $data['status'] = ($result == false) ? 2 : 1;
                //$this->logResult('业务逻辑执行：'.$result);
            }
            
            $arr     = ['return_code' => 'SUCCESS', 'return_msg' => 'OK'];
        } else {
            $data['status'] = 2;
            $data['remark'] = '验证失败';
            $arr = ['return_code' => 'FAIL', 'return_msg' => $data['return_msg']];
        }

        echo $this->array_to_xml($arr);
        //记录日志
        $this->getWxHistory($data);

    }

    /**
     * 衫德回调
     * @return [type] [description]
     */
    public function notifySd(Request $request) 
    {
                // 回调主要数据json解析 -- 结果为对象
        $returnParams = $request->all();

        $data = json_decode($returnParams['data'], true);

        // 支付平台返回码
        $head = $data['head'];

        if($head['respCode'] == '000000'){

            $body       = $data['body'];

            $money      = $body['totalAmount'];
 
             //业务逻辑
            $orderModel = new Order();

            $money      = $money/100;
            //核实订单是否为平台订单
            $result     = $orderModel->check($body['orderCode'], $money);

            if ($result) {

                //$order_sn       = substr($body['orderCode'], -1, 2);
                //订单业务处理
                $result         = $orderModel->edit_pay_order($body['orderCode'], PayModel::TYPE_SDEPAY);

                $data['remark'] = ($result == false) ? '订单业务流程更改失败' : '订单业务流程更改成功';
                $data['status'] = ($result == false) ? 2 : 1;

            } else {

                $data['status'] = 2;
                $data['remark'] = '非法订单';
            }

            echo 'respCode=000000';
        } else {
            $data['error_msg']  = $this->getSdErrorMsg($head['respCode']);
            $data['code']       = $head['respCode'];
            $data['status']     = 2;
            $data['remark']     = '验证失败';
        }

        //记录日志
        $this->getSdHistory($returnParams,$data);
    }

    /**
     *  获得配置参数
     * @return [type] [description]
     */
    public function getConfig($flag) {

        switch ($flag) {
            case 'alipayapp':
                $pay = PayModel::where('type',PayModel::TYPE_ALIPAY)->first();

                break;
            case 'wxpayapp':
                $pay = PayModel::where('type',PayModel::TYPE_WXPAY)->first();
                break;
            case 'sdapppay':
                $pay = PayModel::where('type',PayModel::TYPE_SDEPAY)->first();
                break;             
            default:
                $pay = [];
                break;
        }

      
        return unserialize($pay->params);

    }

      

 
    /**
     * 组合微信插入日志的数据
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    public function getWxHistory($data) {

        extract($data);

        $payHistory = new PayHistory();

        $payHistory->trade_no   =  $transaction_id;
        $payHistory->ordernum   =  $out_trade_no;
        $payHistory->money      =  $total_fee;
        $payHistory->params     =  serialize($data);
        $payHistory->type       =  2;
        $payHistory->status     =  $status;
        $payHistory->remark     =  isset($remark) ? $remark : '';
       
        $payHistory->save();
    }

    /**
     * 组合支付宝支付插入日志数组
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    public function getAliHistory($data) {

        extract($data);

        $payHistory = new PayHistory();

        $payHistory->trade_no   =  $trade_no;
        $payHistory->ordernum   =  $out_trade_no;
        $payHistory->money      =  $total_amount;
        //$params['remark']     =  isset($extra_common_param) ? $extra_common_param : '';
        $payHistory->params     =  serialize($data);
        $payHistory->type       =  1;
        $payHistory->status     =  $status;
        $payHistory->remark     =  isset($remark) ? $remark : '';
       
        $payHistory->save();
    }

    /**
     * 组合衫德插入日志的数据
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    public function getSdHistory($params ,$data) {

 

        $payHistory = new PayHistory();

        $payHistory->trade_no   =  $data['body']['tradeNo'];
        $payHistory->ordernum   =  $data['body']['orderCode'];
        $payHistory->money      =  $data['body']['totalAmount'];
        $payHistory->params     =  serialize($params);
        $payHistory->type       =  4;
        $payHistory->status     =  $data['status'];
        $payHistory->remark     =  isset($data['remark']) ? $data['remark'] : '';
        $payHistory->code       =  $data['code'];
        $payHistory->error_msg  =  isset($data['error_msg']) ? $data['error_msg'] : '';
       
        $payHistory->save();
    }
    /**
     * 检测是否开启支付
     * @return [type] [description]
     */
    public function checkStatus($flag) {

        $payModel = new PayModel();

        $result  = NULL;

        if ($flag == 'wxpayapp') 
            $result = $payModel->where('type', PayModel::TYPE_WXPAY)->first();

        if ($flag == 'alipayapp')
            $result = $payModel->where('type', PayModel::TYPE_ALIPAY)->first();
       
        if ($flag == 'shande')
            $result = $payModel->where('type', PayModel::TYPE_SDEPAY)->first();

        return ($result == null) ? false : true; 
    }

    /**
     * @Author   wang
     * @DateTime 2017-02-06
     * @param    [type]     $params [description]  数组数据
     * @return   [type]             [description]  数组转xml
     */
    function array_to_xml($params) {

        if (!is_array($params) || count($params) <= 0) {
            return false;
        }
        $xml = "<xml>";
        foreach ($params as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }


    /**
     * 验证支付结果
     * @return [type] [description]
     */
    public function checkResult(Request $request) 
    {

        $order_sn = $request->input('order_sn');
        
        if ($order_sn == null ) {
            return self::error('订单号为空');
        }

        $result = Order::where('order_sn', $order_sn)->where('status', 1)->first();

        if (empty($result)) {

            //查询订单历史表获得失败原因
            $history = PayHistory::where('ordernum',$order_sn)->first();

            $errorMsg = empty($history) ? '未支付订单' : $history->remark;

            return self::error($errorMsg);

        } else {

            $data['pay_type']     = $this->payName[$result->pay_method];
            $data['pay_money']    = (string) $result->pay_amount;
            $data['pay_discount'] = (string) ($result->total_amount - $result->pay_amount);

            return self::json($data);
        }
    }

    /**
     * 衫德获得错误信息
     * @param  [type] $code [description]
     * @return [type]       [description]
     */
    public function getSdErrorMsg($code) 
    {
        $errorCode = array(
            '000001' => '银行返回超时',
            '000002' => '银行处理异常',
            '000003' => '平台处理异常',
            '010001' => '商户不存在',
            '010002' => '商户已停用',
            '010003' => '商户未开通此产品',
            '010004' => 'IP非法',
            '020001' => '请求参数有误',
            '000001' => '签名验证未通过',
            '030001' => '重复订单',
            '030002' => '无可用渠道',
            '030003' => '单笔金额超限',
            '030004' => '当日累计金额超限',
            '030005' => '查询订单不存在',
            '030006' => '原订单不用存在',
            '030007' => '退款金额大于可退金额',
            '030008' => '对账文件未生成',
            '030009' => '原支付订单未成功，无法退款',
            '030010' => '订单超过有效时间，失效',
            '030011' => '不支持当日退款',
            '030012' => '支付模式未开通',
            '999999' => '未知错误',
            );
        return isset($errorCode[$code]) ? $errorCode[$code] : '错误回执码';
    }

    /**
     * 写日志，方便测试（看网站需求，也可以改成把记录存入数据库）
     * 注意：服务器需要开通fopen配置
     * @param $word 要写入日志里的文本内容 默认值：空值
     */
    public  function logResult($word='') {

        //$path = dirname(__DIR__)."/log.txt";
        $path =  "/home/wwwroot/youxiang/storage/log.txt";
        $fp   = fopen($path,"a");
        flock($fp, LOCK_EX) ;
        //fwrite($fp,"执行日期：".strftime("%Y%m%d%H%M%S",time())." ".$word."\n");
        fwrite($fp,$word."\n");
        flock($fp, LOCK_UN);
        fclose($fp);
    }

    /**
     * 取日志，方便测试（看网站需求，也可以改成把记录存入数据库）
     * 注意：服务器需要开通fopen配置
     * @param $word 要写入日志里的文本内容 默认值：空值
     */
    public  function getLog($word='') {

        //$path = "/home/wwwroot/zhaiquanjinxitong/storage/log.txt";
  
        //$path ="/home/wwwroot/youxiang/storage/log.txt";
        
        $path = 'D:\phpStudy\WWW\newApp\youxiang\storage\testLog.txt';
        $myfile =  fopen($path, "r");
        $word = fread($myfile,filesize($path));
        return $word;
    }
}
